/**
 * 一、定义
 * 1.1 通用类型参数默认类型
 * 参数是通用类型，但是又可以给这个参数一个默认类型。
 * 语法是：<PlaceholderType=ConcreteType> ，或者简写为诸如<T=xxx>,其中xxx是某个具体的类型。
 * 这种现象类似于typescript
 * class MyClass<T = number> {
    value: T;
    constructor(value: T) {
        this.value = value;
    }
    printValue(): void {
        console.log(`Value is ${this.value}`);
    }
}

const obj1 = new MyClass(42);  // 使用默认类型 number
const obj2 = new MyClass<string>("Hello");  // 使用指定类型 string
 *
 * 1.2 运算符重载
 * 难于理解，还是看代码吧！
 * 实际这也是rust的自己实现的，按照它的那一套来就可以了。
 *
 * 二、通用类型参数默认类型的意义
 * 1.扩展类型而不破坏现有代码。
 * 2.在大部分用户都不需要的特定情况进行自定义
 * 这两句话如果没有例子，或者没有解释还是比较难于阅读的
 * //, PartialEq, Clone，Copy
 */
use std::ops::{Add,Sub};
#[derive(Debug, Clone,Copy)]
struct Point {
    x: i32,
    y: i32,
}
/**
 * 这个使用默认类型，来自rust编程语言官方文档的例子
 */
impl Add for Point {
    type Output = Point;
    fn add(self, other: Point) -> Point {
        Point {
            x: self.x + other.x,
            y: self.y + other.y,
        }
    }
}

/**
 * 实现相减运算符（从而实现Point的-重载)，需要实现Sub trait
 */
impl Sub for Point {
    type Output = Point;
    /**
     * 需要特别注意的是两个参数的定义
     * self -  没有使用引用
     * other - 没有要求引用
     * 这种不引用的方式，不同于一般的方法定义,因为Point实现了Copy,Clone所以，传参的时候不会转移所有权
     */
    fn sub(self, other: Point) -> Point {
        Point {
            x: self.x - other.x,
            y: self.y - other.y,
        }
    }
}

#[derive(Debug)]
struct trangle{
    a:Point,
    b:Point,
    c:Point
}

fn main() {
    let p1 = Point { x: 1, y: 2 };
    let p2 = Point { x: 3, y: 4 };
    //使用重载的方式调用
    println!("{:?}+{:?}={:?}",p1,p2, p1 + p2);
    println!("{:?}-{:?}={:?}",p1,p2, p1 - p2);

    //不使用重载的方式调用
    let p3 = p1.add(p2).sub(p2);
    let p4 = (p1.sub(p2)).add(p2);
    println!("{:?}+{:?}-{:?}={:?}",p1,p2, p2,p3);
    println!("{:?}-{:?}+{:?}={:?}",p1,p2,p2, p4);

    //演示三角形
    let t = trangle{a:p1,b:p2,c:Point { x: 5, y: 6 }};
    println!("{:?}",t);
    println!("{:?}",p1);
}